import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import axios from 'axios'
import { get, merge } from 'lodash-es'
import { useUserStore } from '@/pinia/stores/user'
import { getToken } from '@/utils/cache/cookies'
import { codeMessage } from '@/utils/constants/request-key'

const logout = function () {
  useUserStore().logout()
  location.reload()
}

/** 创建请求实例 */
const createInstance = function () {
  const service = axios.create()

  // 请求拦截器
  service.interceptors.request.use(
    (config) => {
      // 发送之前

      if (useUserStore().token) {
        config.headers['X-Token'] = getToken()
      }
      return config
    },
    (error) => {
      // 发送失败
      console.log(error)
      return Promise.reject(error)
    }
  )

  // 响应拦截器（可根据具体业务作出相应的调整）
  service.interceptors.response.use(
    (response) => {
      const apiData = response.data
      // 二进制数据则直接返回
      const responseType = response.request?.responseType
      if (responseType === 'blob' || responseType === 'arraybuffer')
        return apiData

      // 这个 code 是和后端约定的业务 code
      const code = apiData.code
      // 如果没有 code, 代表这不是项目后端开发的 api
      if (code === undefined) {
        ElMessage.error('非本系统的接口')
        console.warn('非本系统的接口')
        return Promise.reject(new Error('非本系统的接口'))
      }
      switch (code) {
        case 0:
          // 本系统采用 code === 0 来表示没有业务错误
          return apiData
        case 401:
          // Token 过期时
          return logout()
        default:
          // 不是正确的 code
          ElMessage.error(apiData.message || 'Error')
          console.warn(apiData.message || 'Error')
          return Promise.reject(new Error('Error'))
      }
    },
    (error) => {
      // status 是 HTTP 状态码
      const status: number = get(error, 'response.status')
      const message = get(error, 'response.statusText')
      const errorText = codeMessage[status] || message
      ElMessage.error(error.message)
      console.warn(errorText)
      return Promise.reject(error)
    }
  )

  return service
}

/** 创建请求方法 */
const createRequest = function (instance: AxiosInstance) {
  return <T>(config: AxiosRequestConfig): Promise<T> => {
    const token = getToken()
    // 默认配置
    const defaultConfig: AxiosRequestConfig = {
      // 接口地址
      baseURL: import.meta.env.VITE_BASE_URL,
      // 请求头
      headers: {
        // 携带 Token
        Authorization: token ? `Bearer ${token}` : undefined,
        'Content-Type': 'application/json'
      },
      // 请求体
      data: {},
      // 请求超时
      timeout: 5000,
      // 跨域请求时是否携带 Cookies
      withCredentials: false
    }
    // 将默认配置 defaultConfig 和传入的自定义配置 config 进行合并成为 mergeConfig
    const mergeConfig = merge(defaultConfig, config)
    return instance(mergeConfig)
  }
}

/** 用于请求的实例 */
const instance = createInstance()

/** 用于请求的方法 */
export const request = createRequest(instance)
